package cn.virens.common.utils.objcet;

import cn.virens.common.exception.APIException;

import java.io.*;

/**
 * 序列化工具
 *
 * @author : virens
 */
public class SerializableUtil {
    /**
     * 将对象序列化为byte数组
     *
     * @param object 待序列化对象
     * @return byte数组
     * @throws APIException 解析异常
     */
    public static byte[] serialize(Object object) throws APIException {
        try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
            return serialize(object, stream).toByteArray();
        } catch (IOException e) {
            throw APIException.warp(e);
        }
    }

    /**
     * 对象序列化
     *
     * @param <T>          序列化结果输出流类型
     * @param object       待序列化对象
     * @param outputStream 序列化结果输出流
     * @return 序列化结果输出流
     * @throws APIException 解析异常
     */
    public static <T extends OutputStream> T serialize(Object object, T outputStream) throws APIException {
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) {
            objectOutputStream.writeObject(object);
            objectOutputStream.flush();
        } catch (IOException e) {
            throw APIException.warp(e);
        }

        return outputStream;
    }

    /**
     * 反序列化
     *
     * @param bs    byte数组
     * @param clazz 对象类
     * @param <T>   对象
     * @return 反序列化的对象
     */
    public static <T> T deserialize(byte[] bs, Class<T> clazz) {
        return ObjectUtil.to(deserialize(bs), clazz);
    }

    /**
     * 反序列化
     *
     * @param <T> 返回值类型
     * @param bs  byte数组
     * @return 反序列化的对象
     * @throws APIException 解析异常
     */
    public static <T> T deserialize(byte[] bs) throws APIException {
        try (InputStream stream = new ByteArrayInputStream(bs)) {
            return deserialize(stream);
        } catch (IOException e) {
            throw APIException.warp(e);
        }
    }

    /**
     * 反序列化
     *
     * @param inputStream 输入流
     * @param clazz       对象类
     * @param <T>         对象
     * @return 反序列化的对象
     */
    public static <T> T deserialize(InputStream inputStream, Class<T> clazz) {
        return ObjectUtil.to(deserialize(inputStream), clazz);
    }

    /**
     * 反序列化
     *
     * @param <T>         返回值类型
     * @param inputStream 输入流
     * @return 反序列化的对象
     * @throws APIException 解析异常
     */
    @SuppressWarnings("unchecked")
    public static <T> T deserialize(InputStream inputStream) throws APIException {
        try (ObjectInputStream stream = new ObjectInputStream(inputStream)) {
            return (T) stream.readObject();
        } catch (Exception e) {
            throw APIException.warp(e);
        }
    }
}
